
#ifndef UTILS_FILE_LOCK
#define UTILS_FILE_LOCK

#include <string>
#include <stdexcept>
#include <cstring>

// 区分Windows和Linux平台
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/file.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#endif

namespace equip_system
{

class Singleton
{
public:
    // 禁止拷贝和赋值
    Singleton(const Singleton &) = delete;
    Singleton &operator=(const Singleton &) = delete;

    // 获取单例实例
    static Singleton &getInstance(const std::string &lockFilePath = "EquipServer.lock")
    {
        static Singleton instance(lockFilePath);
        return instance;
    }

    // 检查是否有其他实例运行
    bool isAnotherInstanceRunning() const
    {
        return isRunning_;
    }

private:
    Singleton(const std::string &lockFilePath) : lockFile_(lockFilePath), isRunning_(false)
    {
#ifdef _WIN32
        // Windows平台文件锁实现
        hFile_ = CreateFileA(
            lockFile_.c_str(),
            GENERIC_READ | GENERIC_WRITE,
            0, // 不共享，其他进程无法打开
            NULL,
            CREATE_ALWAYS, // 不存在则创建，存在则打开
            FILE_ATTRIBUTE_NORMAL,
            NULL);

        if (hFile_ == INVALID_HANDLE_VALUE)
        {
            // 如果打开失败，可能是被其他进程锁定
            DWORD err = GetLastError();
            if (err == ERROR_SHARING_VIOLATION)
            {
                isRunning_ = true; // 其他进程已锁定
                return;
            }
            throw std::runtime_error("创建锁文件失败: " + std::to_string(err));
        }

        // 尝试锁定整个文件
        OVERLAPPED overlapped = {0};
        if (!LockFileEx(
                hFile_,
                LOCKFILE_EXCLUSIVE_LOCK, // 排他锁
                0,                       // 不共享
                MAXDWORD, MAXDWORD,      // 锁定整个文件
                &overlapped))
        {
            DWORD err = GetLastError();
            CloseHandle(hFile_);
            hFile_ = INVALID_HANDLE_VALUE;
            if (err == ERROR_LOCK_VIOLATION)
            {
                isRunning_ = true; // 已被其他进程锁定
                return;
            }
            throw std::runtime_error("获取文件锁失败: " + std::to_string(err));
        }
#else
        // Linux平台文件锁实现（保持原逻辑）
        fd_ = open(lockFile_.c_str(), O_CREAT | O_RDWR, 0666);
        if (fd_ == -1)
        {
            throw std::runtime_error("打开锁文件失败: " + std::string(strerror(errno)));
        }

        if (flock(fd_, LOCK_EX | LOCK_NB) == -1)
        {
            if (errno == EWOULDBLOCK || errno == EAGAIN)
            {
                isRunning_ = true;
            }
            else
            {
                throw std::runtime_error("获取文件锁失败: " + std::string(strerror(errno)));
            }
            close(fd_);
            fd_ = -1;
        }
#endif
    }

    ~Singleton()
    {
#ifdef _WIN32
        // Windows释放锁和文件句柄
        if (hFile_ != INVALID_HANDLE_VALUE)
        {
            UnlockFileEx(hFile_, 0, MAXDWORD, MAXDWORD, &overlapped_);
            CloseHandle(hFile_);
            DeleteFileA(lockFile_.c_str()); // 删除锁文件
        }
#else
        // Linux释放锁和文件描述符
        if (fd_ != -1)
        {
            flock(fd_, LOCK_UN);
            close(fd_);
            unlink(lockFile_.c_str());
        }
#endif
    }

private:
    std::string lockFile_; // 锁文件路径
#ifdef _WIN32
    HANDLE hFile_ = INVALID_HANDLE_VALUE; // Windows文件句柄
    OVERLAPPED overlapped_ = {0};         // 用于文件锁定
#else
    int fd_ = -1; // Linux文件描述符
#endif
    bool isRunning_; // 是否有其他实例运行
};

} // namespace equip_system

#endif //